package com.example.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;

public class Server {

	private static ServerSocket serverSocket;
	private static Socket clientSocket;
	private static HashMap<String, PrintWriter> clientList = new HashMap<String, PrintWriter>();
	private static HashMap<String, ArrayList<String>> flags = new HashMap<String, ArrayList<String>>();
	private static ArrayList<String> banned = new ArrayList<String>();
	private static String message;
	private static int port = 8000;

	public void relay(String msg, String from) {
		System.out.println("Tentei fazer relay");
		for (String user : clientList.keySet()) {
			if (!from.equals(user) && !banned.contains(from)) {
				PrintWriter printer = clientList.get(user);
				System.out.println(msg);
				printer.println(msg);
				printer.flush();
			}
		}
	}

	public void relayTo(String msg, String to) {
		System.out.println("Tentei fazer to relay");
		for (String user : clientList.keySet()) {
			if (to.equals(user)) {
				PrintWriter printer = clientList.get(user);
				System.out.println(msg);
				printer.println(msg);
				printer.flush();
			}
		}
	}
	
	public void flag(String from, String to) {
		if (banned.contains(to))
			return;
		else if (!flags.containsKey(from)){
			ArrayList<String> temp1 = new ArrayList<String>();
			temp1.add(to);
			flags.put(from, temp1);
		} 
		if (!flags.get(from).contains(to)) {
				ArrayList<String> temp = flags.get(from);
				temp.add(to);
				flags.put(from, temp);
				int aux = 0;
				for(ArrayList<String> temp2 : flags.values()){
					if (temp2.contains(to))
						aux++;
				}
				if (aux >= (Math.round(clientList.size() / 2)))
					banned.add(to);
		}
	}
	
	public String messageProcessor(String message, Socket socket) throws IOException {
	
	if (message.startsWith("Reg:")) {
		
		PrintWriter pw = new PrintWriter(new OutputStreamWriter(
				socket.getOutputStream()));
		String[] msgParts = message.split(":", 2);
		String user = msgParts[1];
		clientList.put(user, pw);
		System.out.println("Estou a registar");
		return "reg done";

	} else if (message.startsWith("To:")) {
		
		String[] msgParts = message.split(":", 4);
		String toUser = msgParts[1];
		String fromUser = msgParts[2];
		relayTo(message, toUser);
		
	} else if (message.startsWith("Unreg:")){
		
		String[] msgParts = message.split(":", 2);
		String user = msgParts[1];
		clientList.remove(user);
		if (banned.contains(user))
			banned.remove(user);
		
		return "unreg done";
	} else if (message.startsWith("Flag:")){
		
		String[] msgParts = message.split(":", 3);
		String from = msgParts[1];
		String to = msgParts[2];
		flag(from, to);
		return "flag done";
		
	} else {
		
		String[] msgParts = message.split(":", 2);
		String user = msgParts[0];
		relay(message, user);
		return "relay done";
		
	}
	return "normal";
	}

	public void startServer() {

		try {
			serverSocket = new ServerSocket(port);


		while (true) {
				
				System.out.println("Novo Socket");
				clientSocket = serverSocket.accept();

				new ComThread(clientSocket).start();
				continue;

			}
		}
		catch (IOException ex) {
				System.out.println("Problem in message reading");
			}
		}

	public static void main(String[] args) {
		try {
			System.out.println("NearTweet server started. Listening on IP '"
					+ InetAddress.getLocalHost().getHostAddress()
					+ "' and port '" + port + "'.");
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}

		new Server().startServer();

	}

	private class ComThread extends Thread {
		private Socket socket;

		public ComThread(Socket socket) {
			this.socket = socket;
		}

		public void run() {

			try {
				System.out.println("New Thread started.");
				
				BufferedReader bufferedReader = new BufferedReader(
						new InputStreamReader(socket.getInputStream()));

				while(true) {


					message = bufferedReader.readLine();
					System.out.println(message);

					if(message == null)
						break;
					else {

						String status = Server.this.messageProcessor(message, socket);
						System.out.println("check" + status);

					}
				}
			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}